import asyncio
from .logger_config import log_info, log_debug, log_warning, log_error, log_success, log_failure, log_progress, log_connection, log_media, log_stats
import logging
import random
import time
import traceback
import uuid
from collections.abc import Callable
from typing import Optional, Union

from av import AudioFrame
from av.frame import Frame

from . import clock, rtp
from .codecs import get_capabilities, get_encoder, is_rtx
from .codecs.base import Encoder
from .exceptions import InvalidStateError
from .mediastreams import MediaStreamError, MediaStreamTrack
from .rtcdtlstransport import RTCDtlsTransport
from .rtcrtpparameters import (
    RTCRtpCapabilities,
    RTCRtpCodecParameters,
    RTCRtpSendParameters,
)
from .rtp import (
    RTCP_PSFB_APP,
    RTCP_PSFB_PLI,
    RTCP_RTPFB_NACK,
    RTP_HISTORY_SIZE,
    AnyRtcpPacket,
    RtcpByePacket,
    RtcpPsfbPacket,
    RtcpRrPacket,
    RtcpRtpfbPacket,
    RtcpSdesPacket,
    RtcpSenderInfo,
    RtcpSourceInfo,
    RtcpSrPacket,
    RtpPacket,
    unpack_remb_fci,
    wrap_rtx,
)
from .stats import (
    RTCOutboundRtpStreamStats,
    RTCRemoteInboundRtpStreamStats,
    RTCStatsReport,
)
from .utils import random16, random32, uint16_add, uint32_add
from .fec import FecConfig, FecPacket, BaseFecCodec

logger = logging.getLogger(__name__)

RTT_ALPHA = 0.85


def random_sequence_number() -> int:
    """
    Generate a random RTP sequence number.

    The sequence number is chosen in the lower half of the allowed range in
    order to avoid wraparounds which break SRTP decryption.

    See:
    https://chromiumdash.appspot.com/commit/13b327b05fa3788b4daa9c3463e13282824cb320
    """
    return random16() % 32768


class RTCEncodedFrame:
    def __init__(self, payloads: list[bytes], timestamp: int, audio_level: int, encode_time_ms: float = 0.0):
        self.payloads = payloads
        self.timestamp = timestamp
        self.audio_level = audio_level
        self.encode_time_ms = encode_time_ms


class RTCRtpSender:
    """
    The :class:`RTCRtpSender` interface provides the ability to control and
    obtain details about how a particular :class:`MediaStreamTrack` is encoded
    and sent to a remote peer.

    :param trackOrKind: Either a :class:`MediaStreamTrack` instance or a
                         media kind (`'audio'` or `'video'`).
    :param transport: An :class:`RTCDtlsTransport`.
    """

    def __init__(
        self, trackOrKind: Union[MediaStreamTrack, str], transport: RTCDtlsTransport
    ) -> None:
        if transport.state == "closed":
            raise InvalidStateError

        if isinstance(trackOrKind, MediaStreamTrack):
            self.__kind = trackOrKind.kind
            self.replaceTrack(trackOrKind)
        else:
            self.__kind = trackOrKind
            self.replaceTrack(None)
        
        self.__transport = transport
        self.__loop = asyncio.get_event_loop()

        # RTP
        self._ssrc = random32()
        self._rtx_ssrc = random32()
        self.__sequence_number = random_sequence_number()
        self.__timestamp_origin = random32()
        self.__rtp_started = asyncio.Event()
        self.__rtp_exited = asyncio.Event()
        self.__rtp_task: Optional[asyncio.Future] = None

        # RTCP
        self.__rtcp_started = asyncio.Event()
        self.__rtcp_exited = asyncio.Event()
        self.__rtcp_task: Optional[asyncio.Future] = None

        # encoder
        self.__encoder: Optional[Encoder] = None
        self.__total_frames_encoded = 0
        self.__total_encode_time = 0.0
        self.__encoder_initialized = False

        # RTCP
        self.__cname = None
        self.__mid = None
        self.__lsr = None
        self.__lsr_time = None
        self.__rtt = None

        # RTP header extensions
        self.__rtp_header_extensions_map = rtp.HeaderExtensionsMap()

        # RTX
        self.__rtx_payload_type = None
        self.__rtx_sequence_number = random_sequence_number()

        # stats
        self.__stats = RTCStatsReport()
        self.__packet_count = 0
        self.__octet_count = 0
        self.__ntp_timestamp = 0
        self.__rtp_timestamp = 0

        # RTP history for retransmission
        self.__rtp_history = {}
        self.__force_keyframe = False

        # started flag
        self.__started = False

        # FEC相关属性
        self.fec_codec: Optional[BaseFecCodec] = None
        self.fec_ssrc = random32() & 0xFFFFFFFF  # 确保SSRC在32位范围内
        self.fec_buffer = []

        # Additional required attributes
        self._enabled = True
        self._stream_id = str(uuid.uuid4())

        # logging
        self.__log_debug: Callable[..., None] = lambda *args: None
        if logger.isEnabledFor(logging.DEBUG):
            self.__log_debug = lambda msg, *args: logger.debug(
                f"RTCRtpSender(%s) {msg}", self.__kind, *args
            )

    @property
    def kind(self) -> str:
        return self.__kind

    @property
    def track(self) -> MediaStreamTrack:
        """
        The :class:`MediaStreamTrack` which is being handled by the sender.
        """
        return self.__track

    @property
    def transport(self) -> RTCDtlsTransport:
        """
        The :class:`RTCDtlsTransport` over which media data for the track is
        transmitted.
        """
        return self.__transport

    @classmethod
    def getCapabilities(self, kind: str) -> RTCRtpCapabilities:
        """
        Returns the most optimistic view of the system's capabilities for
        sending media of the given `kind`.

        :rtype: :class:`RTCRtpCapabilities`
        """
        return get_capabilities(kind)

    async def getStats(self) -> RTCStatsReport:
        """
        Returns statistics about the RTP sender.

        :rtype: :class:`RTCStatsReport`
        """
        self.__stats.add(
            RTCOutboundRtpStreamStats(
                # RTCStats
                timestamp=clock.current_datetime(),
                type="outbound-rtp",
                id="outbound-rtp_" + str(id(self)),
                # RTCStreamStats
                ssrc=self._ssrc,
                kind=self.__kind,
                transportId=self.transport._stats_id,
                # RTCSentRtpStreamStats
                packetsSent=self.__packet_count,
                bytesSent=self.__octet_count,
                # RTCOutboundRtpStreamStats
                trackId=str(id(self.track)),
                totalFramesEncoded=self.__total_frames_encoded,  # 累计编码帧数
                totalEncodeTime=self.__total_encode_time,  # 累计编码总时间
            )
        )
        self.__stats.update(self.transport._get_stats())

        return self.__stats

    def replaceTrack(self, track: Optional[MediaStreamTrack]) -> None:
        self.__track = track
        if track is not None:
            self._track_id = track.id
        else:
            self._track_id = str(uuid.uuid4())

    def setTransport(self, transport: RTCDtlsTransport) -> None:
        self.__transport = transport

    def getParameters(self) -> RTCRtpSendParameters:
        """
        Returns the current parameters for the RTP sender.
        
        :rtype: :class:`RTCRtpSendParameters`
        """
        # 创建基本的参数对象
        parameters = RTCRtpSendParameters()
        
        # 如果已经启动，从当前配置中获取参数
        if self.__started:
            parameters.muxId = self.__mid or ""
            if self.__cname:
                parameters.rtcp.cname = self.__cname
                parameters.rtcp.ssrc = self._ssrc
        
        # 设置FEC配置
        if self.fec_codec:
            parameters.fec_config = self.fec_codec.config
        
        return parameters
    
    async def setParameters(self, parameters: RTCRtpSendParameters) -> None:
        """
        Sets the parameters for the RTP sender.
        
        :param parameters: The :class:`RTCRtpSendParameters` for the sender.
        """
        # 更新FEC配置
        if hasattr(parameters, 'fec_config') and parameters.fec_config:
            # 如果FEC配置发生变化，重新创建FEC编解码器
            if not self.fec_codec or self.fec_codec.config != parameters.fec_config:
                self.fec_codec = self._create_fec_codec(parameters.fec_config)
                log_debug("FEC codec updated: {fec_type}", fec_type=parameters.fec_config.fec_type)
        elif hasattr(parameters, 'fec_config') and parameters.fec_config is None:
            # 禁用FEC
            self.fec_codec = None
            self._fec_buffer.clear()
            log_debug("FEC disabled")

    async def send(self, parameters: RTCRtpSendParameters) -> None:
        """
        Attempt to set the parameters controlling the sending of media.

        :param parameters: The :class:`RTCRtpSendParameters` for the sender.
        """
        if not self.__started:
            self.__cname = parameters.rtcp.cname
            self.__mid = parameters.muxId

            # make note of the RTP header extension IDs
            self.__transport._register_rtp_sender(self, parameters)
            self.__rtp_header_extensions_map.configure(parameters)

            # make note of RTX payload type
            for codec in parameters.codecs:
                if (
                    is_rtx(codec)
                    and codec.parameters["apt"] == parameters.codecs[0].payloadType
                ):
                    self.__rtx_payload_type = codec.payloadType
                    break

            # 配置FEC
            if hasattr(parameters, 'fec_config') and parameters.fec_config:
                self.fec_codec = self._create_fec_codec(parameters.fec_config)
                log_debug("RTCRtpSender.send - 配置FEC: {fec_type}", fec_type=parameters.fec_config.fec_type)
            if hasattr(parameters, 'fec_ssrc'):
                log_debug("RTCRtpSender.send - FEC SSRC: {fec_ssrc}", fec_ssrc=parameters.fec_ssrc)

            self.__rtp_task = asyncio.ensure_future(self._run_rtp(parameters.codecs[0]))
            self.__rtcp_task = asyncio.ensure_future(self._run_rtcp())
            self.__started = True

    async def stop(self) -> None:
        """
        Irreversibly stop the sender.
        """
        if self.__started:
            self.__transport._unregister_rtp_sender(self)

            # shutdown RTP and RTCP tasks
            await asyncio.gather(self.__rtp_started.wait(), self.__rtcp_started.wait())
            self.__rtp_task.cancel()
            self.__rtcp_task.cancel()
            await asyncio.gather(self.__rtp_exited.wait(), self.__rtcp_exited.wait())

    async def _handle_rtcp_packet(self, packet: AnyRtcpPacket) -> None:
        if isinstance(packet, (RtcpRrPacket, RtcpSrPacket)):
            for report in filter(lambda x: x.ssrc == self._ssrc, packet.reports):
                # estimate round-trip time
                if self.__lsr == report.lsr and report.dlsr:
                    rtt = time.time() - self.__lsr_time - (report.dlsr / 65536)
                    if self.__rtt is None:
                        self.__rtt = rtt
                    else:
                        self.__rtt = RTT_ALPHA * self.__rtt + (1 - RTT_ALPHA) * rtt

                self.__stats.add(
                    RTCRemoteInboundRtpStreamStats(
                        # RTCStats
                        timestamp=clock.current_datetime(),
                        type="remote-inbound-rtp",
                        id="remote-inbound-rtp_" + str(id(self)),
                        # RTCStreamStats
                        ssrc=packet.ssrc,
                        kind=self.__kind,
                        transportId=self.transport._stats_id,
                        # RTCReceivedRtpStreamStats
                        packetsReceived=self.__packet_count - report.packets_lost,
                        packetsLost=report.packets_lost,
                        jitter=report.jitter,
                        # RTCRemoteInboundRtpStreamStats
                        roundTripTime=self.__rtt,
                        fractionLost=report.fraction_lost,
                    )
                )
        elif isinstance(packet, RtcpRtpfbPacket) and packet.fmt == RTCP_RTPFB_NACK:
            for seq in packet.lost:
                await self._retransmit(seq)
        elif isinstance(packet, RtcpPsfbPacket) and packet.fmt == RTCP_PSFB_PLI:
            self._send_keyframe()
        elif isinstance(packet, RtcpPsfbPacket) and packet.fmt == RTCP_PSFB_APP:
            try:
                bitrate, ssrcs = unpack_remb_fci(packet.fci)
                if self._ssrc in ssrcs:
                    self.__log_debug(
                        "- receiver estimated maximum bitrate %d bps", bitrate
                    )
                    if self.__encoder and hasattr(self.__encoder, "target_bitrate"):
                        self.__encoder.target_bitrate = bitrate
            except ValueError:
                pass

    async def _next_encoded_frame(
        self, codec: RTCRtpCodecParameters
    ) -> Optional[RTCEncodedFrame]:
        # Get [Frame|Packet].
        data = await self.__track.recv()

        # If the sender is disabled, drop the frame instead of encoding it.
        # We still want to read from the track in order to avoid frames
        # accumulating in memory.
        if not self._enabled:
            return None

        audio_level = None

        if self.__encoder is None:
            self.__encoder = get_encoder(codec)

        if isinstance(data, Frame):
            # Encode the frame.
            if isinstance(data, AudioFrame):
                audio_level = rtp.compute_audio_level_dbov(data)

            force_keyframe = self.__force_keyframe
            self.__force_keyframe = False
            
            # 记录编码开始时间
            encode_start_time = time.perf_counter()
            payloads, timestamp = await self.__loop.run_in_executor(
                None, self.__encoder.encode, data, force_keyframe
            )
            # 计算编码时延
            encode_end_time = time.perf_counter()
            encode_time_ms = (encode_end_time - encode_start_time) * 1000
            
            # 更新编码时延统计
            self.__total_frames_encoded += 1
            self.__total_encode_time += encode_time_ms

        else:
            # Pack the pre-encoded data.
            payloads, timestamp = self.__encoder.pack(data)
            encode_time_ms = 0.0

        # If the encoder did not return any payloads, return `None`.
        # This may be due to a delay caused by resampling.
        if not payloads:
            return None

        # 调试信息：显示每帧的分包数
        try:
            log_stats("[{kind_upper}][ENCODE] 帧分包数: {payloads_len}, 时间戳: {timestamp}, 编码时延: {encode_time_ms:.2f}ms",
                     kind_upper=self.__kind.upper(), payloads_len=len(payloads), timestamp=timestamp, encode_time_ms=encode_time_ms)
        except Exception:
            pass

        return RTCEncodedFrame(payloads, timestamp, audio_level, encode_time_ms)

    async def _retransmit(self, sequence_number: int) -> None:
        """
        Retransmit an RTP packet which was reported as lost.
        """
        packet = self.__rtp_history.get(sequence_number % RTP_HISTORY_SIZE)
        if packet and packet.sequence_number == sequence_number:
            if self.__rtx_payload_type is not None:
                packet = wrap_rtx(
                    packet,
                    payload_type=self.__rtx_payload_type,
                    sequence_number=self.__rtx_sequence_number,
                    ssrc=self._rtx_ssrc,
                )
                self.__rtx_sequence_number = uint16_add(self.__rtx_sequence_number, 1)

            self.__log_debug("> %s", packet)
            packet_bytes = packet.serialize(self.__rtp_header_extensions_map)
            await self.transport._send_rtp(packet_bytes)
            
            # 调试信息：显示重传时的历史大小
            history_size = len(self.__rtp_history)
            try:
                log_stats("[{kind_upper}] 重传包: 序列号={sequence_number}, 历史大小={history_size}/{rtp_history_size}",
                         kind_upper=self.__kind.upper(), sequence_number=sequence_number, 
                         history_size=history_size, rtp_history_size=RTP_HISTORY_SIZE)
            except Exception:
                pass
        else:
            # 调试信息：显示重传失败
            history_size = len(self.__rtp_history)
            try:
                log_stats("[{kind_upper}] 重传失败: 序列号={sequence_number}, 历史大小={history_size}/{rtp_history_size}",
                         kind_upper=self.__kind.upper(), sequence_number=sequence_number, 
                         history_size=history_size, rtp_history_size=RTP_HISTORY_SIZE)
            except Exception:
                pass

    def _send_keyframe(self) -> None:
        """
        Request the next frame to be a keyframe.
        """
        self.__force_keyframe = True

    async def _run_rtp(self, codec: RTCRtpCodecParameters) -> None:
        self.__log_debug("- RTP started")
        self.__rtp_started.set()

        # 添加统计变量
        self.__stats_counter = 0
        self.__last_stats_time = time.time()

        sequence_number = random_sequence_number()
        timestamp_origin = random32()
        try:
            while True:
                if not self.__track:
                    await asyncio.sleep(0.02)
                    continue

                # Fetch the next encoded frame. This can be `None` if the sender
                # is disabled, in which case we just continue the loop.
                enc_frame = await self._next_encoded_frame(codec)
                if enc_frame is None:
                    continue

                timestamp = uint32_add(timestamp_origin, enc_frame.timestamp)

                for i, payload in enumerate(enc_frame.payloads):
                    packet = RtpPacket(
                        payload_type=codec.payloadType,
                        sequence_number=sequence_number,
                        timestamp=timestamp,
                    )
                    packet.ssrc = self._ssrc
                    packet.payload = payload
                    packet.marker = (i == len(enc_frame.payloads) - 1) and 1 or 0

                    # set header extensions
                    packet.extensions.abs_send_time = (
                        clock.current_ntp_time() >> 14
                    ) & 0x00FFFFFF
                    packet.extensions.mid = self.__mid
                    if enc_frame.audio_level is not None:
                        packet.extensions.audio_level = (False, -enc_frame.audio_level)

                    # send packet
                    self.__log_debug("> %s", packet)
                    self.__rtp_history[packet.sequence_number % RTP_HISTORY_SIZE] = (
                        packet
                    )
                    
                    # 调试信息：显示发送重传历史大小
                    try:
                        history_size = len(self.__rtp_history)
                        # 计算包的总大小（包括RTP头部、扩展和载荷）
                        packet_bytes = packet.serialize(self.__rtp_header_extensions_map)
                        packet_size = len(packet_bytes)
                        payload_size = len(packet.payload)
                        log_stats("[{kind_upper}] 重传历史大小: {history_size}/{rtp_history_size},序列号: {packet_sequence_number}, 包大小: {packet_size}字节 (载荷: {payload_size}字节)",
                                 kind_upper=self.__kind.upper(), packet_sequence_number=packet.sequence_number, 
                                 history_size=history_size, rtp_history_size=RTP_HISTORY_SIZE,
                                 packet_size=packet_size, payload_size=payload_size)
                    except Exception:
                        pass
                    
                    packet_bytes = packet.serialize(self.__rtp_header_extensions_map)
                    await self.transport._send_rtp(packet_bytes)

                    # 生成并发送FEC包
                    if self.fec_codec:
                        try:
                            # 将当前包添加到FEC缓冲区
                            if not hasattr(self, '_fec_buffer'):
                                self._fec_buffer = []
                            
                            self._fec_buffer.append(packet)
                            log_debug("添加包到FEC缓冲区: 序列号={seq}, 缓冲区大小={buffer_size}/{k}", 
                                     seq=packet.sequence_number, buffer_size=len(self._fec_buffer), k=self.fec_codec.config.k)
                            
                            # 当缓冲区达到k个包时，生成FEC包
                            if len(self._fec_buffer) >= self.fec_codec.config.k:
                                log_debug("开始生成FEC包: 缓冲区大小={buffer_size}, k={k}", 
                                         buffer_size=len(self._fec_buffer), k=self.fec_codec.config.k)
                                # 只取前k个包进行FEC编码
                                packets_to_encode = self._fec_buffer[:self.fec_codec.config.k]
                                fec_packets = await self._generate_fec_packets(packets_to_encode)
                                
                                log_debug("生成了 {fec_count} 个FEC包", fec_count=len(fec_packets))
                                
                                # 发送FEC包
                                for i, fec_packet in enumerate(fec_packets):
                                    fec_bytes = fec_packet.serialize(self.__rtp_header_extensions_map)
                                    await self.transport._send_rtp(fec_bytes)
                                    log_media("发送FEC包 {i}/{total}: 序列号={seq}, FEC ID={fec_id}, 保护序列号={protected_seqs}", 
                                             i=i+1, total=len(fec_packets), seq=fec_packet.sequence_number, fec_id=fec_packet.fec_payload_id, 
                                             protected_seqs=fec_packet.protected_sequence_numbers)
                                
                                # 清空缓冲区
                                self._fec_buffer = []
                                
                        except Exception as e:
                            log_error("生成FEC包失败: {e}", e=e)
                            import traceback
                            traceback.print_exc()

                    self.__ntp_timestamp = clock.current_ntp_time()
                    self.__rtp_timestamp = packet.timestamp
                    self.__octet_count += len(payload)
                    self.__packet_count += 1
                    sequence_number = uint16_add(sequence_number, 1)
                    
        except (asyncio.CancelledError, ConnectionError, MediaStreamError):
            pass
        except Exception:
            # we *need* to set __rtp_exited, otherwise RTCRtpSender.stop() will hang,
            # so issue a warning if we hit an unexpected exception
            self.__log_warning(traceback.format_exc())

        # stop track
        if self.__track:
            self.__track.stop()
            self.__track = None

        # release encoder
        self.__encoder = None

        self.__log_debug("- RTP finished")
        self.__rtp_exited.set()

    async def _run_rtcp(self) -> None:
        self.__log_debug("- RTCP started")
        self.__rtcp_started.set()

        try:
            while True:
                # The interval between RTCP packets is varied randomly over the
                # range [0.5, 1.5] times the calculated interval.
                await asyncio.sleep(0.5 + random.random())

                # RTCP SR
                packets: list[AnyRtcpPacket] = [
                    RtcpSrPacket(
                        ssrc=self._ssrc,
                        sender_info=RtcpSenderInfo(
                            ntp_timestamp=self.__ntp_timestamp,
                            rtp_timestamp=self.__rtp_timestamp,
                            packet_count=self.__packet_count & 0xFFFFFFFF,
                            octet_count=self.__octet_count & 0xFFFFFFFF,
                        ),
                    )
                ]
                self.__lsr = ((self.__ntp_timestamp) >> 16) & 0xFFFFFFFF
                self.__lsr_time = time.time()

                # RTCP SDES
                if self.__cname is not None:
                    packets.append(
                        RtcpSdesPacket(
                            chunks=[
                                RtcpSourceInfo(
                                    ssrc=self._ssrc,
                                    items=[(1, self.__cname.encode("utf8"))],
                                )
                            ]
                        )
                    )

                await self._send_rtcp(packets)
        except asyncio.CancelledError:
            pass

        # RTCP BYE
        packet = RtcpByePacket(sources=[self._ssrc])
        await self._send_rtcp([packet])

        self.__log_debug("- RTCP finished")
        self.__rtcp_exited.set()

    def _create_fec_codec(self, config: FecConfig) -> BaseFecCodec:
        """创建FEC编解码器"""
        if config.fec_type == 'reed_solomon':
            from .fec import ReedSolomonFec
            return ReedSolomonFec(config)
        elif config.fec_type == 'xor':
            from .fec import XorFec
            return XorFec(config)
        elif config.fec_type == 'repetition':
            from .fec import RepetitionFec
            return RepetitionFec(config)
        else:
            raise ValueError(f"Unsupported FEC type: {config.fec_type}")

    async def _generate_fec_packets(self, rtp_packets: list[RtpPacket]) -> list[RtpPacket]:
        """生成FEC包"""
        if not self.fec_codec or not rtp_packets:
            return []
        
        try:
            # 生成FEC包
            fec_packets = self.fec_codec.encode(rtp_packets)
            fec_rtp_packets = []
            
            for fec_packet in fec_packets:
                # 创建FEC RTP包
                fec_ssrc = self.fec_ssrc & 0xFFFFFFFF  # 确保SSRC在32位范围内
                fec_rtp_packet = RtpPacket(
                    payload_type=97,  # FEC payload type (使用97避免与音频Opus的96冲突)
                    sequence_number=self.__sequence_number,
                    timestamp=int(time.time() * 90000),  # timestamp会在构造函数中自动处理
                    ssrc=fec_ssrc,
                    payload=fec_packet.repair_payload
                )
                
                # 设置FEC属性
                fec_rtp_packet.is_fec_packet = True
                fec_rtp_packet.fec_payload_id = fec_packet.fec_payload_id
                fec_rtp_packet.protected_sequence_numbers = fec_packet.protected_sequence_numbers
                
                # 调试：显示FEC包属性
                log_debug("设置FEC包属性: fec_payload_id={fec_payload_id}, protected_sequence_numbers={protected_sequence_numbers}", 
                         fec_payload_id=fec_packet.fec_payload_id, protected_sequence_numbers=fec_packet.protected_sequence_numbers)
                
                # 确保protected_sequence_numbers不为空
                if not fec_rtp_packet.protected_sequence_numbers:
                    log_warning("FEC包protected_sequence_numbers为空，尝试修复")
                    # 从FEC包ID推断保护的序列号
                    if fec_packet.fec_payload_id is not None:
                        fec_rtp_packet.protected_sequence_numbers = [fec_packet.fec_payload_id]
                    else:
                        fec_rtp_packet.protected_sequence_numbers = [fec_rtp_packet.sequence_number - 1]
                    log_debug("修复后的protected_sequence_numbers: {protected_sequence_numbers}", 
                             protected_sequence_numbers=fec_rtp_packet.protected_sequence_numbers)
                
                fec_rtp_packets.append(fec_rtp_packet)
                self.__sequence_number = uint16_add(self.__sequence_number, 1)
            
            return fec_rtp_packets
        except Exception as e:
            log_error("生成FEC包时出错: {e}", e=e)
            return []

    async def _send_rtcp(self, packets: list[AnyRtcpPacket]) -> None:
        payload = b""
        for packet in packets:
            self.__log_debug("> %s", packet)
            payload += bytes(packet)

        try:
            await self.transport._send_rtp(payload)
        except ConnectionError:
            pass

    def __log_warning(self, msg: str, *args: object) -> None:
        logger.warning(f"RTCRtpsender(%s) {msg}", self.__kind, *args)
